﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SmartRoute.Data;

namespace SmartRoute.Analytics
{
    public struct SimpleParameters
    {
        private int _passengerLimit;

        public int PassengerLimit
        {
          get { return _passengerLimit; }
          set { _passengerLimit = value; }
        }

        private TimeSpan _ridingTimeLimit;

        public TimeSpan RidingTimeLimit
        {
          get { return _ridingTimeLimit; }
          set { _ridingTimeLimit = value; }
        }

        public SimpleParameters(TimeSpan timeLimit, int passengerLimit)
        {
            _passengerLimit = passengerLimit;
            _ridingTimeLimit = timeLimit;
        }

    }

    [Serializable]
    public class Analyzer<TParameters>
    {
        private TParameters _parameters;

        public TParameters Parameters
        {
            get { return _parameters; }
            set { _parameters = value; }
        }

        private Func<TParameters,IEnumerable<Bus>,double> _test;

        public double runTest(IEnumerable<Bus> toBeTested)
        {
            return _test(_parameters,toBeTested);
        }

        public Analyzer(Func<TParameters,IEnumerable<Bus>,double> test, TParameters parameters)
        {
            _test = test;
            _parameters = parameters;
        }

        /// <summary>
        /// The fitness test as constructed by Andrew Smigaj
        /// </summary>
        /// <param name="passengerLimit">Maximum number of passengers to allow on a bus</param>
        /// <param name="timeLimit">Maximum number of time a passenger may spend on a bus</param>
        /// <returns>A fitness test according to Andrew's specification.</returns>
        public static Analyzer<SimpleParameters> FitnessTest(int passengerLimit, TimeSpan timeLimit)
        {
            return new Analyzer<SimpleParameters>(
                ((SimpleParameters parameters, IEnumerable<Bus> buses) =>
                    {
                        double accum = 0;
                        foreach (var bus in buses)
                        {
                            if (bus.TimeStudentSpentOnBus > parameters.RidingTimeLimit)
                                return 1;
                            if (bus.Passengers > parameters.PassengerLimit)
                                return 1;
                            accum += bus.Duration.Seconds;
                        }
                        return 1000000/accum;
                    }),
                    new SimpleParameters(timeLimit,passengerLimit));
        }

        protected Analyzer() { }
    }
}
